package references

import "jvmgo/ch06/instructions/base"
import "jvmgo/ch06/rtda"
import "jvmgo/ch06/rtda/heap"

// 设置类中的静态字段
type PUT_STATIC struct {
    base.Index16Instruction
}

func (self *PUT_STATIC) Execute(frame *rtda.Frame) {
    currentMethod := frame.Method()
    currentClass := currentMethod.Class()
    cp := currentClass.ConstantPool()
    fieldRef := cp.GetConstant(self.Index).(*heap.FieldRef)
    field := fieldRef.ResolvedField()
    class := field.Class()
    // todo: 类初始化

    if !field.IsStatic() {
        panic("java.lang.IncompatibleClassChangeError")
    }
    if field.IsFinal() {
        if currentClass != class || currentMethod.Name() != "<clinit>" {
            panic("java.lang.IllegalAccessError")
        }
    }

    descriptor := field.Descriptor()
    slotId := field.SlotId()
    slots := class.StaticVars()
    stack := frame.OperandStack()

    switch descriptor[0] {
    case 'Z', 'B', 'C', 'S', 'I':
        slots.SetInt(slotId, stack.PopInt())
    case 'F':
        slots.SetFloat(slotId, stack.PopFloat())
    case 'J':
        slots.SetLong(slotId, stack.PopLong())
    case 'D':
        slots.SetDouble(slotId, stack.PopDouble())
    case 'L', '[':
        slots.SetRef(slotId, stack.PopRef())
    default:
    // todo
    }
}
